package hr.sting.droidorm.dao;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import hr.sting.beans.PropertyInfo;
import hr.sting.droidorm.DroidOrmCursor;
import hr.sting.droidorm.DroidOrmManager;
import hr.sting.droidorm.OrmEntityDescriptor;
import hr.sting.droidorm.types.IntegerOrmTypeMapper;
import hr.sting.droidorm.types.OrmTypeMapper;
import hr.sting.droidorm.types.StringOrmTypeMapper;
import hr.sting.droidorm.util.PropertyReplacer;

/**
 * @author mstipanov
 * @since 10.07.2010. 16:58:55
 */
public class DroidOrmTemplate {
    private DroidOrmManager ormManager;
    private OrmTypeMapper ormTypeMapper = new StringOrmTypeMapper(new IntegerOrmTypeMapper(null));
    private PropertyReplacer propertyReplacer = new PropertyReplacer();

    public DroidOrmTemplate(DroidOrmManager ormManager) {
        this.ormManager = ormManager;
    }

    public <T> DroidOrmCursor<T> query(Class<T> entityType, String selection, String[] selectionValues) {
        OrmEntityDescriptor<T> descriptor = ormManager.getOrmEntityDescriptor(entityType);

        selection = convertProperties(selection, descriptor);

        SQLiteDatabase database = ormManager.getSqLiteOpenHelper().getReadableDatabase();
        Cursor cursor = database.query(descriptor.getTableName(), descriptor.getColumnNames(), selection, selectionValues, null, null, null);

        return new DroidOrmCursor<T>(cursor, descriptor, ormTypeMapper);
    }

    private <T> String convertProperties(String selection, OrmEntityDescriptor<T> descriptor) {
        return propertyReplacer.replaceProperties(selection, descriptor);
    }

    public <T> void saveOrUpdate(Class<T> entityType, T t) {
        OrmEntityDescriptor<T> descriptor = ormManager.getOrmEntityDescriptor(entityType);
        if (descriptor.isSaved(t)) {
            update(descriptor, t);
            return;
        }

        save(descriptor, t);
    }

    public <T> void delete(Class<T> entityType, T t) {
        if (null == t) {
            return;
        }

        OrmEntityDescriptor<T> descriptor = ormManager.getOrmEntityDescriptor(entityType);
        ormManager.getSqLiteOpenHelper().getWritableDatabase().delete(descriptor.getTableName(), descriptor.getPrimaryKeyColumnName() + " = ?", new String[]{descriptor.getPrimaryKeyValue(t)});
    }

    private <T> void update(OrmEntityDescriptor<T> descriptor, T t) {
        SQLiteDatabase writableDatabase = ormManager.getSqLiteOpenHelper().getWritableDatabase();
        String tableName = descriptor.getTableName();
        ContentValues contentValues = getContentValues(descriptor, t);
        String where = descriptor.getPrimaryKeyColumnName() + " = ?";
        String primaryKeyValue = descriptor.getPrimaryKeyValue(t);
        writableDatabase.update(tableName, contentValues, where, new String[]{primaryKeyValue});
    }

    private <T> void save(OrmEntityDescriptor<T> descriptor, T t) {
        SQLiteDatabase writableDatabase = ormManager.getSqLiteOpenHelper().getWritableDatabase();
        String tableName = descriptor.getTableName();
        ContentValues contentValues = getContentValues(descriptor, t);
        writableDatabase.insert(tableName, null, contentValues);
    }

    private <T> ContentValues getContentValues(OrmEntityDescriptor<T> descriptor, T t) {
        ContentValues contentValues = new ContentValues();
        for (String columnName : descriptor.getColumnNames()) {
            if (descriptor.isPrimaryKey(columnName)) {
                continue;
            }

            PropertyInfo property = descriptor.getProperty(columnName);
            Object value = property.getValue(t);
            ormTypeMapper.putContentValue(contentValues, columnName, property.getPropertyType(), value);
        }
        return contentValues;
    }
}
